package com.lichao.FinkDataProcess.pojo;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.lichao.FinkDataProcess.compare.StringCompareNode;
import com.lichao.FinkDataProcess.rel.AndNode;
import com.lichao.FinkDataProcess.rel.OrNode;
import com.lichao.FinkDataProcess.rel.RelNode;

public class RuleBuilder {

    public static RelNode buildRule(String arguments) throws Exception {
        JSONObject ruleJson = JSONObject.parseObject(arguments);
        String relation = ruleJson.getString("relation");
        RelNode relNode = "and".equals(relation) ? new AndNode() : new OrNode();

        JSONArray conditions = ruleJson.getJSONArray("conditions");
        for (Object cond : conditions) {
            JSONObject condJson = (JSONObject) cond;
            String fieldName = condJson.getString("fieldName");
            String operateType = condJson.getString("operateType");
            Object value = condJson.get("value");

            switch (operateType) {
                case "=":
                case "!=":
                case "in":
                    StringCompareNode stringCompareNode = new StringCompareNode(fieldName, operateType, value);
                    relNode.add(stringCompareNode);
                    break;
                default:
            }

            if (condJson.containsKey("conditions")) {
                // Nested rule
                RelNode buildRule = buildRule(String.valueOf(cond));
                relNode.add(buildRule);
            }
        }

        return relNode;
    }

    public static boolean apply(String ruleJsonStr, JSONObject value) throws Exception {
        RelNode relNode = buildRule(ruleJsonStr);
        return relNode.apply(value);
    }

    public static void main(String[] args) {
        try {
            String ruleJsonStr = "{\n" +
                    "    \"conditions\": [\n" +
                    "        {\"fieldName\": \"moduleid\", \"operateType\": \"=\", \"value\": \"123\"},\n" +
                    "        {\"fieldName\": \"pageid\", \"operateType\": \"!=\", \"value\": \"123\"},\n" +
                    "        {\"fieldName\": \"eventid\", \"operateType\": \"in\", \"value\": [\"kh\", \"ku_test\"],\"conditions\": [\n" +
                    "        {\"fieldName\": \"moduleid\", \"operateType\": \"=\", \"value\": \"123\"},\n" +
                    "        {\"fieldName\": \"pageid\", \"operateType\": \"!=\", \"value\": \"123\"},\n" +
                    "        {\"fieldName\": \"eventid\", \"operateType\": \"in\", \"value\": [\"kh\", \"ku_test\"]}],\n" +
                    "       \"relation\":\"or\"}],\n" +
                    "       \"relation\":\"and\"\n" +
                    "}";

            JSONObject value = new JSONObject();
            value.put("moduleid", "123");
            value.put("pageid", "456");
            value.put("eventid", "ku_test");

            boolean result = RuleBuilder.apply(ruleJsonStr, value);
            System.out.println("Result: " + result);

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static boolean compare(Rules rule, String value) {
        RelNode relNode = rule.getRelNode();
        try {
            return relNode.apply(JSONObject.parseObject(value));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
